'use strict';

const BaseController = require('../../core/base_controller');
const axios = require('axios');

class UserController extends BaseController {
    async getCountState() {
        const {ctx} = this
        const {user_id} = ctx.request.headers
        if (!user_id) {
            ctx.throw(400, '缺少用户id')
        }
        let publish_num = await ctx.model.JobOpening.count({
            where: {status: 1, del_flag: 0, user_id}
        })
        let collect_num = await ctx.model.UserCollect.count({where: {user_id}})
        let browse_num = await ctx.model.UserBrowse.count({where: {user_id}})
        this.success({
            publish_num,
            collect_num,
            browse_num,
        })
    }

    async getCoverShiftHistory() {
        const {ctx} = this;
        let {type = 1} = ctx.query;
        type = Number(type);
        let data
        if (type === 1) {
            data = await this.getCoverShiftBrowse()
        } else {
            data = await this.getCoverShiftCollect()
        }
        this.success(data)
    }

    async getHistory() {
        const {ctx} = this;
        let {type = 1} = ctx.query;
        type = Number(type);
        let data
        if (type === 1) {
            data = await this.getBrowse(ctx.query)
        } else {
            data = await this.getCollect(ctx.query)
        }
        this.success(data)
    }

    async getCoverShiftCollect() {
        return new Promise(async (resolve, reject) => {
            try {
                const {ctx} = this;
                const {user_id} = ctx.headers
                const {page = 1, pageSize = 10} = ctx.query;
                const {count, rows} = await ctx.model.UserCollect.findAndCountAll({
                    order: [['created_at', 'DESC']],
                    where: {user_id, type: 'shift_work'},
                    offset: (page - 1) * pageSize,
                    limit: parseInt(pageSize)
                });
                for (let item of rows) {
                    item = item.dataValues
                    let job = await ctx.model.CoverShift.findOne({
                        where: {
                            id: item.collect_id
                        },
                        include: [
                            {
                                model: ctx.model.User,
                                attributes: ['real_name', 'avatar', 'sex', 'birth_day', 'phone'],
                            },
                            {model: ctx.model.Position, as: 'position', attributes: ['name', 'id']},
                            {
                                model: ctx.model.DictionaryDetail,
                                as: 'workExperience',
                                attributes: ['dict_value', 'dict_key', 'id']
                            }
                        ]
                    })
                    item.job = job.dataValues
                }
                resolve({
                    list: rows,
                    pagination: {
                        total: count,
                        current: parseInt(page),
                        pageSize: parseInt(pageSize),
                    }
                })
            } catch (e) {
                reject(e)
            }
        })

    }

    async getCollect({page = 1, pageSize = 10}) {
        return new Promise(async (resolve, reject) => {
            try {
                const {ctx} = this;
                const {user_id} = ctx.headers
                const {count, rows} = await ctx.model.UserCollect.findAndCountAll({
                    order: [['created_at', 'DESC']],
                    where: {user_id, type: 'job'},
                    offset: (page - 1) * pageSize,
                    limit: parseInt(pageSize)
                });
                for (let item of rows) {
                    item = item.dataValues
                    let job = await ctx.model.JobOpening.findOne({
                        where: {
                            id: item.collect_id
                        },
                        include: [
                            {model: ctx.model.Position, as: 'position', attributes: ['name', 'id']}
                        ]
                    })
                    item.job = job.dataValues
                    if (item.job) {
                        if (item.job.user_type === 'user') {
                            item.job.user = await ctx.model.UserResumes.findOne({
                                where: {user_id: item.job.user_id},
                            })
                        }
                        let cuisine_ids = item.job.cuisine_ids ? item.job.cuisine_ids.split(',') : [];
                        item.job.cuisines = await ctx.model.DictionaryDetail.findAll({
                            where: {
                                dict_key: {
                                    [ctx.model.Sequelize.Op.in]: cuisine_ids
                                }
                            },
                            attributes: ['dict_value', 'dict_key', 'id']

                        })
                    }
                }
                resolve({
                    list: rows,
                    pagination: {
                        total: count,
                        current: parseInt(page),
                        pageSize: parseInt(pageSize),
                    }
                })
            } catch (e) {
                reject(e)
            }
        })

    }

    async getCoverShiftBrowse() {
        return new Promise(async (resolve, reject) => {
            try {
                const {ctx} = this;
                const {user_id} = ctx.headers
                const {page = 1, pageSize = 10} = ctx.query;
                const {count, rows} = await ctx.model.UserBrowse.findAndCountAll({
                    order: [['created_at', 'DESC']],
                    where: {user_id, type: 'shift_work'},
                    offset: (page - 1) * pageSize,
                    limit: parseInt(pageSize)
                });
                for (let item of rows) {
                    item = item.dataValues
                    let job = await ctx.model.CoverShift.findOne({
                        where: {
                            id: item.browse_id
                        },
                        include: [
                            {
                                model: ctx.model.User,
                                attributes: ['real_name', 'avatar', 'sex', 'birth_day', 'phone'],
                            },
                            {model: ctx.model.Position, as: 'position', attributes: ['name', 'id']},
                            {
                                model: ctx.model.DictionaryDetail,
                                as: 'workExperience',
                                attributes: ['dict_value', 'dict_key', 'id']
                            }
                        ]
                    })
                    item.job = job.dataValues
                    if (item.job) {
                        let cuisine_ids = item.job.cuisine_ids ? item.job.cuisine_ids.split(',') : [];
                        item.job.cuisines = await ctx.model.DictionaryDetail.findAll({
                            where: {
                                dict_key: {
                                    [ctx.model.Sequelize.Op.in]: cuisine_ids
                                }
                            },
                            attributes: ['dict_value', 'dict_key', 'id']
                        })
                    }

                }
                resolve({
                    list: rows,
                    pagination: {
                        total: count,
                        current: parseInt(page),
                        pageSize: parseInt(pageSize),
                    }
                })
            } catch (e) {
                reject(e)
            }
        })

    }

    async getBrowse({page = 1, pageSize = 10}) {
        return new Promise(async (resolve, reject) => {
            try {
                const {ctx} = this;
                const {user_id} = ctx.headers
                const {page = 1, pageSize = 10} = ctx.query;
                const {count, rows} = await ctx.model.UserBrowse.findAndCountAll({
                    order: [['created_at', 'DESC']],
                    where: {user_id, type: 'job'},
                    offset: (page - 1) * pageSize,
                    limit: parseInt(pageSize)
                });
                for (let item of rows) {
                    item = item.dataValues
                    let job = await ctx.model.JobOpening.findOne({
                        where: {
                            id: item.browse_id
                        },
                        include: [
                            {model: ctx.model.Position, as: 'position', attributes: ['name', 'id']}
                        ]
                    })
                    item.job = job.dataValues

                    if (item.job) {
                        if (item.job.user_type === 'user') {
                            item.job.user = await ctx.model.UserResumes.findOne({
                                where: {user_id: item.job.user_id},
                                attributes: ['real_name', 'id']
                            })
                        }
                        let cuisine_ids = item.job.cuisine_ids ? item.job.cuisine_ids.split(',') : [];
                        item.job.cuisines = await ctx.model.DictionaryDetail.findAll({
                            where: {
                                dict_key: {
                                    [ctx.model.Sequelize.Op.in]: cuisine_ids
                                }
                            },
                            attributes: ['dict_value', 'dict_key', 'id']
                        })
                    }
                }
                resolve({
                    list: rows,
                    pagination: {
                        total: count,
                        current: parseInt(page),
                        pageSize: parseInt(pageSize),
                    }
                })
            } catch (e) {
                reject(e)
            }
        })

    }

    // 保存/更新简历
    async saveResume() {
        const {ctx} = this;
        const resumeData = ctx.request.body;
        if (!resumeData.id) {
            ctx.throw(400, '参数错误')
        }
        let resume = await ctx.model.UserResumes.findOne(
            {id: resumeData.id}
        );
        if (!resume) {
            ctx.throw(500, '简历不存在')
        }
        let user = null
        if (resumeData.avatar && resumeData.avatar !== resume.avatar) {
            user = await ctx.model.User.findOne({where: {user_id: resume.user_id}})
            await user.update({
                avatar: resumeData.avatar,
            });
        }
        await resume.update(resumeData)
        this.success(user)
    }

    async userVerify() {
        const {ctx} = this;
        const {name, idcard} = ctx.request.body;
        const {user_id} = ctx.headers
        if (!name || !idcard || !user_id) {
            ctx.throw(400, '参数错误')
        }
        const user = await ctx.model.User.findOne({
            where: {
                user_id
            }
        })
        if (!user) {
            ctx.throw(500, '用户不存在')
        }
        if (user.user_type !== 'user') {
            ctx.throw(500, '该角色不是个人用户')
        }
        if (user.is_certified) {
            ctx.throw(500, '该用户已认证')
        }
        try {
            const url = `https://kzidcardv1.market.alicloudapi.com/api/id_card/check?name=${name}&idcard=${idcard}`
            const res = await ctx.curl(url, {
                method: "GET",
                headers: {
                    'Authorization': 'APPCODE ' + '2dfeadc46f0e49c7b9cbc3979f7be115'
                },
                dataType: 'json'
            })
            console.log(res)
            if (res.data.code === 200) {
                if (!res.data.data.result) {
                    await user.update({
                        sex: res.data.data.sex,
                        is_certified: 1,
                        real_name: name,
                        id_card: idcard,
                        address: res.data.data.address,
                        birth_day: res.data.data.birthday,
                    })
                    ctx.model.UserResumes.create({
                        user_id: user_id,
                        avatar: user.avatar,
                        real_name: name,
                        sex: res.data.data.sex,
                        birth_day: res.data.data.birthday,
                        phone: user.phone,
                    })
                    this.success(user)
                } else {
                    ctx.throw(500, '验证失败，姓名和身份证不一致')
                }

            } else {
                ctx.throw(400, res.data.msg)
            }

        } catch (e) {
            console.log(e.message)
            ctx.throw(500, '请求失败')
        }


    }

    async getUserJobOpening() {
        const {ctx} = this;
        const {page = 1, pageSize = 10} = ctx.query;
        const where = {
            del_flag: 0,
            user_type: 'user',
            status: 1
        };
        const {count, rows} = await ctx.model.JobOpening.findAndCountAll({
            where,
            order: [['created_at', 'DESC']],
            offset: (page - 1) * pageSize,
            limit: parseInt(pageSize),
            include: [
                {model: ctx.model.Position, as: 'position', attributes: ['name', 'id']},
                {model: ctx.model.DictionaryDetail, as: 'workExperience', attributes: ['dict_value', 'dict_key', 'id']},
            ]
        });
        for (let item of rows) {
            item = item.dataValues
            item.user = await ctx.model.UserResumes.findOne({
                user_id: item.user_id,
            })
        }
        this.success({
            list: rows,
            pagination: {
                total: count,
                current: parseInt(page),
                pageSize: parseInt(pageSize),
            }
        })
    }

    async employerVerify() {
        const {ctx} = this;
        const {realName, idCard, companyName, companyAccount} = ctx.request.body;
        const {user_id} = ctx.headers
        if (!realName || !idCard || !user_id || !companyAccount || !companyName) {
            ctx.throw(400, '参数错误')
        }
        const user = await ctx.model.User.findOne({
            where: {
                user_id
            }
        })
        if (!user) {
            ctx.throw(500, '用户不存在')
        }
        if (user.user_type !== 'employer') {
            ctx.throw(500, '该用户角色不是企业')
        }
        if (user.is_certified) {
            ctx.throw(500, '该用户已认证')
        }
        try {
            const url = `http://enterpris0.market.alicloudapi.com/api/ocr/cloudCode/enterprise`
            const res = await ctx.curl(url, {
                method: "POST",
                data: ctx.request.body,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                    'Authorization': 'APPCODE ' + '2dfeadc46f0e49c7b9cbc3979f7be115'
                },
                dataType: 'json'
            })
            console.log(res)
            if (res.data.status === 200) {
                await user.update({
                    is_certified: 1,
                    real_name: realName,
                    id_card: idCard,
                })
                ctx.model.EmployerInfo.create({
                    user_id: user_id,
                    legal_representative: realName,
                    tax_id: companyAccount,
                    avatar: user.avatar,
                    name: companyName,
                    phone_number: user.phone,
                })
                this.success(user)
            } else {
                ctx.throw(400, res.data.message)
            }

        } catch (e) {
            console.log(e.message)
            ctx.throw(500, '请求失败')
        }


    }


    // 获取用户手机号
    async loginByWeapp() {
        const {ctx} = this;
        const {access_token, code,login_res,user_type='user'} = ctx.request.body
        console.log(access_token, code)
        const res = await axios.post(
            `https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=${access_token}`,
            {code}
        )
        const phone  = res.data.phone_info?.phoneNumber
        if(res.data?.phone_info && res.data?.phone_info?.phoneNumber){
            const {appId,appSecret} = this.config.weapp
            const open_id_data = await axios.post(
                `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${appSecret}&js_code=${login_res.code}&grant_type=authorization_code`
            )
            let user = await ctx.model.User.findOne({where: {phone}});
            if(user){
                if (user.user_type !== user_type) {
                    ctx.throw(500, '该手机号已被注册')
                }
                if (user.del_flag) {
                    ctx.throw(500, '该用户已删除')
                }
                if (!user.status) {
                    ctx.throw(500, '该用户已被禁用')
                }
            }

            let avatar = Math.floor(Math.random() * 5) + 1;
            avatar = `${this.config.static.static_prefix}/public/static/默认头像/${avatar}.png`
            if (!user) {
                user = await ctx.model.User.create({
                    phone,
                    openid:open_id_data.data?.openid,
                    user_type,
                    avatar,
                    status: 1,
                });
            }

            // 生成 token
            const token = ctx.app.jwt.sign({
                user_id: user.user_id,
                phone: user.phone,
                user_type,
            }, ctx.app.config.jwt.secret);
            this.success({
                token,
                userInfo: ctx.service.user.formatUserInfo(user),
            });
        }else{
            ctx.throw(500,'获取手机号失败')
        }
    }

    // 获取微信 accessToken
    async getAccessToken() {
        const {appId, appSecret} = this.config.weapp;
        const result = await this.ctx.curl(
            `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`,
            {
                dataType: 'json',
            }
        );

        if (result.data.errcode) {
            throw new Error(`获取access_token失败: ${result.data.errmsg}`);
        }
        this.success(result.data.access_token)
    }

    // 手机号验证码登录
    async loginByPhone() {
        const {ctx} = this;
        const {phone, code, user_type = 'user'} = ctx.request.body;

        // 参数验证
        const rules = {
            phone: {
                type: 'string',
                required: true,
                format: /^1[3-9]\d{9}$/,
                message: '请输入正确的手机号',
            },
            code: {
                type: 'string',
                required: true,
                format: /^\d{6}$/,
                message: '验证码格式错误',
            }
        };

        try {
            ctx.validate(rules);
        } catch (err) {
            console.log(err)
            const errors = err.errors.map(error => rules[error.field].message).join(', ');
            ctx.throw(400, errors);
        }

        // 验证验证码
        const cacheCode = await ctx.service.cache.get(`sms_code_${phone}`);
        if (!cacheCode || cacheCode !== code) {
            ctx.throw(400, '验证码错误或已过期');
        }

        // 查找或创建用户
        let user = await ctx.model.User.findOne({where: {phone}});
        if(user){
            if ( user.user_type !== user_type) {
                ctx.throw(500, '该手机号已被注册')
            }
            if (user.del_flag) {
                ctx.throw(500, '该用户已删除')
            }
            if (!user.status) {
                ctx.throw(500, '该用户已被禁用')
            }
        }


        let avatar = Math.floor(Math.random() * 5) + 1;
        avatar = `${this.config.static.static_prefix}/public/static/默认头像/${avatar}.png`
        if (!user) {
            user = await ctx.model.User.create({
                phone,
                user_type,
                avatar,
                status: 1,
            });
        }

        // 生成 token
        const token = ctx.app.jwt.sign({
            user_id: user.user_id,
            phone: user.phone,
            user_type,
        }, ctx.app.config.jwt.secret);

        // 清除验证码
        await ctx.service.cache.del(`sms_code_${phone}`);

        this.success({
            token,
            userInfo: ctx.service.user.formatUserInfo(user),
        });
    }

    // 发送验证码
    async sendSmsCode() {
        const {ctx} = this;
        const {phone} = ctx.request.body;

        // 参数验证
        const rules = {
            phone: {
                type: 'string',
                required: true,
                format: /^1[3-9]\d{9}$/,
                message: '请输入正确的手机号',
            },
        };

        try {
            ctx.validate(rules);
        } catch (err) {
            ctx.throw(400, err.message);
        }

        // 检查是否频繁发送
        const lastSendTime = await ctx.service.cache.get(`sms_time_${phone}`);
        if (lastSendTime && Date.now() - lastSendTime < 60000) {
            ctx.throw(400, '请求过于频繁，请稍后再试');
        }

        // 生成验证码
        const code = Math.random().toString().slice(-6);

        // 保存验证码和发送时间
        await ctx.service.cache.set(`sms_code_${phone}`, code, 300); // 5分钟有效期
        await ctx.service.cache.set(`sms_time_${phone}`, Date.now(), 60); // 1分钟内不能重复发送

        // TODO: 调用短信服务发送验证码
        // await ctx.service.sms.send(phone, code);
        // const res = await ctx.curl(`https://kzsms.market.alicloudapi.com/api/sms/send`, {
        //   method: 'POST',
        //   data: {
        //     templateId:this.app.config.cms.LoginTemplateId,
        //     mobile:phone,
        //     value: code,
        //   },
        //   dataType: 'json',
        // });
        // if(res.data.code===200){
        //   const result = res.data.data.result
        //   this.success(result, '验证码发送成功');
        // }else{
        //   ctx.throw(500, err.message);
        // }
        this.success(code, '验证码发送成功');
    }

    async addExperience() {
        const {ctx} = this;
        const {user_id} = ctx.headers;
        const experienceData = ctx.request.body;

        try {
            const experience = await ctx.model.UserResumeExperience.create({
                ...experienceData,
                user_id
            });
            this.success(experience);
        } catch (e) {
            ctx.throw(500, '工作经历添加失败');
        }
    }

    async getAddressByLat() {
        const {ctx} = this;
        const {longitude, latitude} = ctx.request.body;
        if (!longitude || !latitude) {
            ctx.throw(400, '参数错误')
        }
        const url = 'http://whois.pconline.com.cn/ipAreaCoordJson.jsp'
        const res = await ctx.curl(url, {
            method: "GET",
            data: {json: true, coords: `${longitude},${latitude}`,},
            dataType: 'json'
        })
        this.success(res.data)
    }

    async getExperiences() {
        const {ctx} = this;
        const {resume_id} = ctx.query;
        const {user_id} = ctx.headers;

        const where = {user_id};
        if (resume_id) where.resume_id = resume_id;

        const experiences = await ctx.model.UserResumeExperience.findAll({
            where,
            include: [{model: ctx.model.UserResumes, as: 'resume'}]
        });
        this.success(experiences);
    }

    async getExperienceDetail() {
        const {ctx} = this;
        const {id} = ctx.params;
        if (!id) {
            ctx.throw(400, '参数错误')
        }

        const experiences = await ctx.model.UserResumeExperience.findOne({
            id
        });
        this.success(experiences);
    }

    async updateExperience() {
        const {ctx} = this;
        const {id} = ctx.params;
        const {user_id} = ctx.headers;

        const experience = await ctx.model.UserResumeExperience.findOne({
            where: {id, user_id}
        });
        if (!experience) ctx.throw(404, '记录不存在');

        await experience.update(ctx.request.body);
        this.success(experience);
    }

    async deleteExperience() {
        const {ctx} = this;
        const {id} = ctx.params;
        const {user_id} = ctx.headers;

        const experience = await ctx.model.UserResumeExperience.findOne({
            where: {id, user_id}
        });
        if (!experience) ctx.throw(404, '记录不存在');

        await experience.destroy();
        this.success(null, '删除成功');
    }

    async getResume() {
        const {ctx} = this;
        const user_id = ctx.headers.user_id;

        const resume = await ctx.model.UserResumes.findOne({
            where: {user_id},
            include: [{
                as: 'experiences',
                model: ctx.model.UserResumeExperience
            }]
        });
        this.success(resume);
    }
    async getEmployerInfo(){
        const {ctx} = this;
        const {user_id} = ctx.headers;
        let employer = await ctx.model.EmployerInfo.findOne({
            where:{
                user_id
            }
        })
        this.success(employer)
    }
    async updateEmployerInfo() {
        const {ctx} = this;
        const data = ctx.request.body;
        const {user_id} = ctx.headers;

        // 处理照片上传
        if (data.photos_url) {
            try {
                const uploadRes = await ctx.service.qiniu.uploadBase64(data.photos_url, 'employer/');
                data.photos_url = uploadRes.url;
            } catch (e) {
                ctx.throw(500, '照片上传失败');
            }
        }

        const transaction = await ctx.model.transaction();
        try {
            // 更新或创建雇主信息
            const [employerInfo] = await ctx.model.EmployerInfo.upsert({
                ...data,
                user_id
            }, {transaction});

            // 更新用户类型为雇主
            await ctx.model.User.update({
                user_type: 'employer'
            }, {
                where: {user_id},
                transaction
            });

            await transaction.commit();
            this.success(employerInfo);
        } catch (error) {
            await transaction.rollback();
            ctx.throw(500, '企业信息保存失败');
        }
    }
}

module.exports = UserController;
